package cn.com.cifi.mars.bean.bo.returnPlan;

import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignNosReceiptsDto;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnSignRecordsDto;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.collections4.MapUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 回款NOS签约数据
 * @author: JingYuanXiang
 * @date: 2020/11/12 15:08
 */
@Data
public class ReturnPlanNosSaleDataBO extends ReturnPlanSaleDataBO {
    @ApiModelProperty(name = "returnSignReceiptsList", value = "签约实收列表")
    List<ReturnSignNosReceiptsDto> returnSignReceiptsList;

    //初始化
    @Override
    public void initializeMap(){
        if(CollectionUtils.isNotEmpty(returnSignRecordsList)){
            //组合业态编码Map(key:房间id,value:组合业态编码)
            Map<String, String> combinationProductCodeMap = returnSignRecordsList.stream()
                    .collect(Collectors.toMap(ReturnSignRecordsDto::getRoomId, ReturnSignRecordsDto::getCombinationProductCode,(a,b) -> a));
            //对组合业态编码赋值
            returnSignReceiptsList.forEach(s ->s.setCombinationProductCode(combinationProductCodeMap.get(s.getRoomId())));
        }
        //获取全部的房间
        List<String> roomIdList = returnSignRecordsList.stream().map(ReturnSignRecordsDto::getRoomId).collect(Collectors.toList());

        if(CollectionUtils.isNotEmpty(returnSignRecordsList)){
            this.recordsRoomIdListByGroupIdMap = returnSignRecordsList.stream().
                    collect(Collectors.groupingBy(ReturnSignRecordsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignRecordsDto::getCombinationProductCode,
                                    Collectors.mapping(ReturnSignRecordsDto::getRoomId, Collectors.toList()))));
        }
        if(CollectionUtils.isNotEmpty(returnSignRecordsList)){
            this.recordsMoneyByGroupIdMap = returnSignRecordsList.stream().
                    filter(s->roomIdList.contains(s.getRoomId())).
                    collect(Collectors.groupingBy(ReturnSignRecordsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignRecordsDto::getCombinationProductCode,
                            Collectors.groupingBy(ReturnSignRecordsDto::getRoomId,
                                    Collectors.toMap(ReturnSignRecordsDto::getYearMonth, ReturnSignRecordsDto::getMoney, BigDecimal::add)))));
        }

        if(CollectionUtils.isNotEmpty(returnSignReceiptsList)){
            this.receiptsMoneyByGroupIdMapA = returnSignReceiptsList.stream().
                    filter(s->roomIdList.contains(s.getRoomId())).
                    collect(Collectors.groupingBy(ReturnSignNosReceiptsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignNosReceiptsDto::getCombinationProductCode,
                                    Collectors.groupingBy(ReturnSignNosReceiptsDto::getRoomId,
                                            Collectors.toMap(ReturnSignNosReceiptsDto::getYearMonth, ReturnSignNosReceiptsDto::getMoney, BigDecimal::add)))));

            this.receiptsMoneyByGroupIdMapB = returnSignReceiptsList.stream().
                    filter(s->roomIdList.contains(s.getRoomId())).
                    collect(Collectors.groupingBy(ReturnSignNosReceiptsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignNosReceiptsDto::getCombinationProductCode,
                                    Collectors.groupingBy(ReturnSignNosReceiptsDto::getYearMonth,
                                            Collectors.toMap(ReturnSignNosReceiptsDto::getRoomId, ReturnSignNosReceiptsDto::getMoney, BigDecimal::add)))));

            this.zlReceiptsMoneyByGroupIdMap = returnSignReceiptsList.stream().
                    filter(s->roomIdList.contains(s.getRoomId()) && s.getDataType().equals("增量")).
                    collect(Collectors.groupingBy(ReturnSignNosReceiptsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignNosReceiptsDto::getCombinationProductCode,
                            Collectors.toMap(ReturnSignNosReceiptsDto::getYearMonth, ReturnSignNosReceiptsDto::getMoney, BigDecimal::add))));

            this.clReceiptsMoneyByGroupIdMap = returnSignReceiptsList.stream().
                    filter(s->roomIdList.contains(s.getRoomId()) && s.getDataType().equals("存量")).
                    collect(Collectors.groupingBy(ReturnSignNosReceiptsDto::getGroupId,
                            Collectors.groupingBy(ReturnSignNosReceiptsDto::getCombinationProductCode,
                                    Collectors.toMap(ReturnSignNosReceiptsDto::getYearMonth, ReturnSignNosReceiptsDto::getMoney, BigDecimal::add))));
        }
        if(MapUtils.isEmpty(recordsRoomIdListByGroupIdMap)){
            this.recordsRoomIdListByGroupIdMap = new HashMap<>();
        }
        if(MapUtils.isEmpty(recordsMoneyByGroupIdMap)){
            this.recordsMoneyByGroupIdMap = new HashMap<>();
        }
        if(MapUtils.isEmpty(receiptsMoneyByGroupIdMapB)){
            this.receiptsMoneyByGroupIdMapB = new HashMap<>();
        }
        if(MapUtils.isEmpty(zlReceiptsMoneyByGroupIdMap)){
            this.zlReceiptsMoneyByGroupIdMap = new HashMap<>();
        }
        if(MapUtils.isEmpty(clReceiptsMoneyByGroupIdMap)){
            this.clReceiptsMoneyByGroupIdMap = new HashMap<>();
        }
    }


    /**
     * 获取签约增量实收-指定房间id列表在指定月增量实收的金额
     * @param combinationProductCode 组合业态编码
     * @param yearMonth 年月
     * @return
     */
    @Override
    public BigDecimal getZlReceiptsMoneyByYearMonth(String groupId,String combinationProductCode, String yearMonth) {
        //总金额
        BigDecimal money = BigDecimal.ZERO;

        if(MapUtils.isNotEmpty(zlReceiptsMoneyByGroupIdMap.get(groupId))
                && MapUtils.isNotEmpty(zlReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode))
                && null != zlReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode).get(yearMonth)) {
            return zlReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode).get(yearMonth);
        }else {
            return money;
        }
    }

    /**
     * 获取签约存量实收-指定房间id列表在指定月存量实收的金额
     * @param combinationProductCode 组合业态编码
     * @param yearMonth 年月
     * @return
     */
    @Override
    public BigDecimal getClReceiptsMoneyByYearMonth(String groupId,String combinationProductCode, String yearMonth) {
        //总金额
        BigDecimal money = BigDecimal.ZERO;

        if(MapUtils.isNotEmpty(clReceiptsMoneyByGroupIdMap.get(groupId))
                && MapUtils.isNotEmpty(clReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode))
                && null != clReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode).get(yearMonth)) {
            return clReceiptsMoneyByGroupIdMap.get(groupId).get(combinationProductCode).get(yearMonth);
        }else {
            return money;
        }
    }

    /**
     * 获取签约实收-在等于指定月实收的金额
     * @param combinationProductCode 组合业态编码
     * @param yearMonth 年月
     * @return
     */
    @Override
    public BigDecimal getReceiptsMoneyByYearMonth(String groupId,String combinationProductCode, String yearMonth) {
        //总金额
        BigDecimal money = BigDecimal.ZERO;

        Map<String, BigDecimal> receiptsMoneyMap = new HashMap<>();
        if(MapUtils.isNotEmpty(receiptsMoneyByGroupIdMapB.get(groupId))
                && MapUtils.isNotEmpty(receiptsMoneyByGroupIdMapB.get(groupId).get(combinationProductCode))
                && MapUtils.isNotEmpty(receiptsMoneyByGroupIdMapB.get(groupId).get(combinationProductCode).get(yearMonth))) {
            receiptsMoneyMap = receiptsMoneyByGroupIdMapB.get(groupId).get(combinationProductCode).get(yearMonth);
        }else {
            return money;
        }

        money = receiptsMoneyMap.entrySet().stream().map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);
        return money;
    }

    /**
     * 筛选指定合同id列表中当月及以前的实收大于当月及以前的应收的合同id列表
     * 获取其中当月及以前的实收大于当月及以前的应收的金额合计
     * @param groupId 组团id
     * @param combinationProductCode 组合业态编码
     * @param yearMonth 年月
     * @return
     */
    @Override
    public BigDecimal getRefundable(String groupId,String combinationProductCode, String yearMonth) {
        //总金额
        BigDecimal money = BigDecimal.ZERO;

        //获取房间列表
        List<String> roomIdList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(recordsRoomIdListByGroupIdMap.get(groupId))
                && CollectionUtils.isNotEmpty(recordsRoomIdListByGroupIdMap.get(groupId).get(combinationProductCode))){
            roomIdList = recordsRoomIdListByGroupIdMap.get(groupId).get(combinationProductCode);
        }else {
            return money;
        }


        Map<String, Map<String, BigDecimal>> recordsMap = new HashMap<>();
        Map<String, Map<String, BigDecimal>> receiptsMap = new HashMap<>();
        if(MapUtils.isNotEmpty(recordsMoneyByGroupIdMap.get(groupId)) && MapUtils.isNotEmpty(recordsMoneyByGroupIdMap.get(groupId).get(combinationProductCode))){
            recordsMap = recordsMoneyByGroupIdMap.get(groupId).get(combinationProductCode);
        }
        if(MapUtils.isNotEmpty(receiptsMoneyByGroupIdMapA.get(groupId)) && MapUtils.isNotEmpty(receiptsMoneyByGroupIdMapA.get(groupId).get(combinationProductCode))){
            receiptsMap = receiptsMoneyByGroupIdMapA.get(groupId).get(combinationProductCode);
        }

        for (String roomId : roomIdList){
            //签约金额
            BigDecimal recordsMoney = BigDecimal.ZERO;
            //实收金额
            BigDecimal receiptsMoney = BigDecimal.ZERO;

            Map<String, BigDecimal> recordsMoneyMap = recordsMap.get(roomId);
            Map<String, BigDecimal> receiptsMoneyMap = receiptsMap.get(roomId);

            if(MapUtils.isNotEmpty(recordsMoneyMap)) {
                recordsMoney = recordsMoneyMap.entrySet().stream()
                        .filter(e -> compareYearMonth(e.getKey(), yearMonth) <= 0)
                        .map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);
            }

            if(MapUtils.isNotEmpty(receiptsMoneyMap)) {
                receiptsMoney = receiptsMoneyMap.entrySet().stream()
                        .filter(e -> compareYearMonth(e.getKey(), yearMonth) <= 0)
                        .map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);
            }

            if(receiptsMoney.compareTo(recordsMoney) > 0){
                money = money.add(receiptsMoney.subtract(recordsMoney));
            }
        }

        return money;
    }




}
